
#include <memory.h>

#include "land_base.h"
#include "land_graphics.h"
#include "land_math.h"


#define LAND_2D_CORE

#include "init.h"

static struct {
    LandList* modList;
}ctx = { 0 };

static void
freeScene(LandRef* ref) {
	LandScene* scene = (LandScene*)ref;
	landReleaseRef(scene->canvas);
}

LAND_2D_API LandScene*
landNewScene(unsigned width, unsigned height) {
	LandScene* scene = landNewRef(sizeof(LandScene), freeScene);
	scene->width = width;
	scene->height = width;
	scene->canvas = landNewCanvas(width, height, LAND_MSAA_0);
    landRetainRef(scene->canvas);
    landSceneSize(scene, width, height);
    LandVector color = { 0.f, 0.f, 0.f, 0.f };
    landCanvasColor(scene->canvas, &color);
	return scene;
}

LAND_2D_API void
landDrawScene(LandScene* scene, LandObj* obj) {
    landClearCanvas(scene->canvas);
    scene->draw = NULL;

    LandSceneMod* mods;
    unsigned count;
    landBeginList(ctx.modList);
    while (landNextList(ctx.modList, &mods, &count)) {
        for (unsigned i = 0; i < count; i++) {
            mods[i].beginDraw(scene);
        }
    }
	landVisitObj(obj, NULL, 0);
    landPreDrawObj(scene, obj);
    landBeginList(ctx.modList);
    while (landNextList(ctx.modList, &mods, &count)) {
        for (unsigned i = 0; i < count; i++) {
            mods[i].readyDraw(scene);
        }
    }
    landDrawObj(scene, obj);
    if (scene->draw) {
        landDraw(scene->canvas, scene->draw);
    }
    landFlushCanvas(scene->canvas);
}


LAND_2D_API void
landSceneSize(LandScene* scene, unsigned width, unsigned height) {
    scene->width = width;
    scene->height = height;
    landCanvasSize(scene->canvas, width, height);
    LandVector scale = { 2.f / width, -2.f / height, 1.f, 1.f };
    LandVector move = { -((LandFloat)width * 0.5f), -((LandFloat)height * 0.5f), 0.f, 1.f };
    LandMatrix view;
    landIdentityMatrix(&view);
    landMoveMatrix(&view, &move);
    landScaleMatrix(&view, &scale);
    scene->view = view;
}

LAND_2D_API void
landPushSceneMod(LandSceneMod* mod) {
    landPushList(ctx.modList, mod, 1);
}

int
landInitSceneContext() {
    ctx.modList = landNewList(sizeof(LandSceneMod), 32);
    return 0;
}